import random
import cssutils
import time
import ddddocr
import urllib.request
from rand_wait import RandWait
from playwright.sync_api import Playwright, sync_playwright, expect

import signal
import threading
from queue import Queue

class Sousou:
    def __init__(self,  user_id, pwd) -> None:
        self.user_id = user_id
        self.pwd = pwd
        self.logined = False
        self.rand_wait = RandWait(5*60, 10*60)  # 30-60分钟
        self.rand_wait = RandWait(5*60, 8*60)  # 30-60分钟
        self.queue = Queue(2000)
        self.thread = threading.Thread(target=self.publish_fun)
        self.thread.start()
        self.stop_thread = False
        signal.signal(signal.SIGINT, self._exit_gracefully)
        signal.signal(signal.SIGTERM, self._exit_gracefully)

    def _exit_gracefully(self,signum, frame):
        print("开始退出线程")
        self.stop_thread = True
        
    def exit(self):
        print("主动退出线程")
        self.stop_thread = True

    def download(self, style_url='background-image: url("https://static.geetest.com/pictures/v4_pic/slide_2021_07_14/color5/slide/b6939da235e14bdb872be0adc4d613d5.png");', savepath='temp'):
        style = cssutils.parseStyle(style_url)
        url = style['background-image']
        url = url.replace('url(', '').replace(')', '')
        res = urllib.request.urlopen(url)
        with open(savepath, 'wb') as f:
            f.write(res.read())

    def text_dis(self, bg, slice):
        slide = ddddocr.DdddOcr(det=False, ocr=False)
        with open(bg, 'rb') as f:
            background_bytes = f.read()
        with open(slice, 'rb') as f:
            target_bytes = f.read()
        # res = slide.slide_comparison(target_bytes, background_bytes)
        res = slide.slide_match(
            target_bytes, background_bytes, simple_target=True)
        print(res)
        return res.get('target')[0]

    # 鼠标过轨迹，否则会被小怪兽吃了！
    def get_track(self, distance):  # distance为传入的总距离
        track = []
        current = 0
        mid = distance * 3 / 5
        t = 0.2
        v = 1
        while current < distance:
            if current < mid:
                a = 4
            else:
                a = -2
            v0 = v
            v = v0 + a * t
            move = v0 * t + 1 / 2 * a * t * t
            current += move
            track.append(round(move))
        return track

    # 验证滑动验证码
    def _verification_code(self):
        while True:
            time.sleep(2)
            slice_bg = self.page.locator('.geetest_slice_bg')
            bg = self.page.locator('.geetest_bg')
            arrow_btn = self.page.locator(".geetest_btn")

            if slice_bg.count() == 0 or bg.count() == 0 or arrow_btn.count() == 0 or arrow_btn.bounding_box() is None:
                break

            div_style_slice = slice_bg.get_attribute('style')
            div_style_bg = bg.get_attribute('style')

            self.download(div_style_slice, 'slice.png')
            self.download(div_style_bg, 'bg.png')

            box = arrow_btn.bounding_box()
            print(box)
            self.page.wait_for_timeout(2000)
            x = int(box["x"] + box["width"] / 2)
            y = int(box["y"] + box["height"] / 2)
            self.page.mouse.move(x+random.randint(-5, 5), y+random.randint(-5, 5))
            self.page.wait_for_timeout(500)
            self.page.mouse.down()
            self.page.wait_for_timeout(500)
            x_target = self.text_dis('bg.png', 'slice.png')

            track_list = self.get_track(x_target)
            i = 0
            for track in track_list:
                self.page.mouse.move(x + track, y+random.randint(-2, 2), steps=2)
                x = x+track
                if i < 0.8*track_list.__len__():
                    self.page.wait_for_timeout(random.randint(10, 20))
                else:
                    self.page.wait_for_timeout(random.randint(40, 80))
                i = i+1
            self.page.wait_for_timeout(500)
            self.page.mouse.up()
            self.page.wait_for_timeout(1000)

    # 登录
    def _login(self):
        try:
            self.browser = self.playwright.chromium.launch(headless=False)
            self.context = self.browser.new_context()
            self.page = self.context.new_page()
            self.page.goto("https://m.sousou.pro/")
            self.page.get_by_role("link", name="登录", exact=True).click()
            self.page.locator("input[name=\"username\"]").click()
            self.page.locator("input[name=\"username\"]").fill(self.user_id)
            self.page.locator("input[name=\"password\"]").click()
            self.page.locator("input[name=\"password\"]").fill(self.pwd)
            self.page.get_by_role("button", name=" 登录").click()

            self._verification_code()

        except:
            print('登录异常！')

        time.sleep(2)

    # 发布内容
    def _publish(self, class_name, title, text) -> None:
        try:
            self.rand_wait.wait()
            self.page.get_by_role("link", name="发布帖子").click()
            self.page.get_by_placeholder("请输入标题").fill(title)
            self.page.frame_locator(
                "iframe[title=\"富文本区域。按Alt-Shift-H获取帮助。\"]").locator("#tinymce").fill(text)
            self.page.get_by_text("请选择", exact=True).click()
            time.sleep(1)
            self.page.locator("#plate_select_tab_main").get_by_text(
                class_name).click()
            self.page.get_by_text("提交发布").click()
            self._verification_code()
            time.sleep(3)
        except:
            print('发布异常！')

    # 释放浏览器信息
    def _release_browser(self):
        if self.page:
            self.page.close()
            self.context.close()
            self.browser.close()

    # 发布
    def publish(self, class_name, title, text):
        self.queue.put([class_name, title, text])

    # 批量发布
    def publishs(self, publish_infos):
        for publish_info in publish_infos:
            self.queue.put(publish_info)
            # self.publish(publish_info[0], publish_info[1], publish_info[2])

    def publish_fun(self):
        with sync_playwright() as self.playwright:
            self._login()
            while not self.stop_thread:
                publish_info = self.queue.get()
                print('开始发布', publish_info)
                self._publish(publish_info[0], publish_info[1], publish_info[2])
            self._release_browser()


if __name__ == '__main__':
    sousou = Sousou('XYLongzzZ', 'Z941562l456753')
    sousou.publishs([('电视剧', 'azzxxx', 'zzzxxx')])

